#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

#define MAX_ITEM 100

sem_t vacio, lleno;
int buffer;

void init(sem_t *sem, int valor_inicial) {
   if (sem_init(sem, 0, valor_inicial)) {
      printf("Error inicializando semaforo\n");
      exit(EXIT_FAILURE);
   }
}

void p(sem_t *sem) {
   if (sem_wait(sem)) {
      printf("Error fatal haciendo sem_wait()\n");
      exit(EXIT_FAILURE);
   }
}

void v(sem_t *sem) {
   if (sem_post(sem)) {
      printf("Error fatal haciendo sem_post()\n");
      exit(EXIT_FAILURE);
   }
}

void *productor(void *nitems) {
   long numitems = (long)nitems;
   long i;

   for (i=0; i<numitems; i++) {
      p(&vacio);
      buffer = rand()%MAX_ITEM;
      printf("productor(): produciendo item: %d\n", buffer);
      v(&lleno);
   }
   pthread_exit(NULL);
}

void *consumidor(void *nitems) {
   long numitems = (long)nitems;
   long i;

   for (i=0; i<numitems; i++) {
      p(&lleno);
      printf("consumidor(): consumiendo item: %d\n", buffer);
      v(&vacio);
   }
   pthread_exit(NULL);
}

int main(int argc, char *argv[]) {
   pthread_t prod, cons; // hilos
   long num_iteraciones; // numero de iteraciones

   if (argc != 2) {
      printf("Uso correcto: %s num-iteraciones\n", argv[0]);
      exit(EXIT_FAILURE);
   }
   num_iteraciones = atoi(argv[1]);

   srand(time(NULL));

   init(&vacio,1);
   init(&lleno,0);

   printf("main(): creando thread productor\n");
   if (pthread_create(&prod, NULL, productor, (void *)num_iteraciones)) {
      printf("Error creando thread productor\n");
      exit(EXIT_FAILURE);
   }

   printf("main(): creando thread consumidor\n");
   if (pthread_create(&cons, NULL, consumidor, (void *)num_iteraciones)) {
      printf("Error creando thread consumidor\n");
      exit(EXIT_FAILURE);
   }

   pthread_exit(NULL);
}

